package com.atguigu.tingshu.user.api;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.common.Login.TingqLogin;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Tag(name = "微信授权登录接口")
@RestController
@RequestMapping("/api/user/wxLogin")
@Slf4j
@SuppressWarnings("all")
public class WxLoginApiController {

    @Autowired
    private UserInfoService userInfoService;
    @Resource
    private WxMaService wxMaService;

    @Autowired
    private KafkaService kafkaService;



    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 小程序端 微信登录
     * @param code
     * @return
     * @throws WxErrorException
     */
    @Operation(summary = "小程序授权登录")
    @GetMapping("/wxLogin/{code}")
    public Result login(@PathVariable String code) throws WxErrorException {
        WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);

        String openid = sessionInfo.getOpenid();

        //判断openid是否存在?不存在 直接注册保存到数据库 ,存在将用户信息保存在redis数据库中
        LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserInfo::getWxOpenId,openid);

        UserInfo userInfo = userInfoService.getOne(wrapper);

        if (userInfo==null){
            userInfo  =  new UserInfo();

            userInfo.setNickname("听书" + IdUtil.getSnowflake().nextId());
            userInfo.setWxOpenId(openid);
            userInfo.setAvatarUrl("https://xiaoxu-n.oss-cn-hangzhou.aliyuncs.com/default_avatar.png");
            userInfo.setIsVip(0);

            //保存 用户:
            userInfoService.save(userInfo);

            //接收消息 异步消息 发送到账户微服务 初始化用户账户信息
            kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER,userInfo.getId().toString());
        }

        //添加到redis数据库中
        String token = UUID.randomUUID().toString().replaceAll("-","");
        UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
        redisTemplate.opsForValue().set(RedisConstant.USER_LOGIN_KEY_PREFIX + token ,
                userInfoVo,
                RedisConstant.USER_LOGIN_KEY_TIMEOUT,
                TimeUnit.SECONDS);

        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        return Result.ok(map);
    }

    @TingqLogin
    @Operation(summary = "获取用户个人信息")
    @GetMapping("/getUserInfo")
    public Result<UserInfoVo> getUserInfo(){
        Long userId = AuthContextHolder.getUserId();
        UserInfoVo userInfoVo  =  userInfoService.getUserInfo(userId);
        return  Result.ok(userInfoVo);
    }

    /**
     * 更新用户信息
     * @param userInfoVo
     * @return
     */
    @TingqLogin
    @Operation(summary = "更新用户信息")
    @PostMapping("/updateUser")
    public Result updateUserInfo(@RequestBody @Validated UserInfoVo userInfoVo){
        Long userId = AuthContextHolder.getUserId();
        userInfoVo.setId(userId);
        userInfoService.updateInfo(userInfoVo);
        return Result.ok();

    }

}
